﻿using System;
using System.Linq;
using System.Text; 
using T.FAS.Runtime.Metadata.Entity.DataModel;
using T.FAS.Runtime.Metadata.Entity;
using DataTypeUtil = T.FAS.Runtime.Metadata.Entity.DataModel.DataTypeUtil;
using T.FAS.Runtime.Base.Entity;

namespace T.FAS.Runtime.DataModel.Dao
{
    /// <summary>
    /// 元数据验证接口
    /// </summary>
    public class StateMachineValidator : IMetaDataDesignValidator, IMetaDataRuntimeValidator
    {
        public string MetaDataType = DataModelConst.StateMachineMetaType;
        public string MetaDataTypeCN = DataModelConst.StateMachineMetaName;
        private readonly CompositeDataObjectLogic _compositeDataObjectLogic = new CompositeDataObjectLogic();
        private readonly StateMachineMetadataLogic _stateMachineMetadataLogic = new StateMachineMetadataLogic();
        //DO依赖DB校验

        public bool CreateMetadata(IMetaDataContent metaDataContent)
        {
            var Assert = GetEntityValidateResult(metaDataContent);
            Assert.FailIfErrorResult();
            return Assert.GetAssertResult().Result;
        }

        public bool DeleteMetadata(IMetaDataContent metaDataContent)
        {
            FASAssert Assert = new FASAssert();
            Assert.IsNotNull(metaDataContent.MetaDataID, $"数据库删除时未指定MetaDataID");
            Assert.FailIfErrorResult();
            return Assert.GetAssertResult().Result;
        }

        public bool GetMetadata(IMetaDataContent metaDataContent)
        {
            var Assert = GetEntityValidateResult(metaDataContent, CRUDType.Retrive);
            Assert.FailIfErrorResult();
            return Assert.GetAssertResult().Result;
        }

        public bool UpdateMetadata(IMetaDataContent metaDataContent)
        {
            //因为目前更新采用先删后加的方式，所以采用相同校验规则
            return CreateMetadata(metaDataContent);
        }

        public bool GetMetadataRTP(IMetaDataContent metaDataContent)
        {
            //目前运行时获取元数据跟设计时一致
            return GetMetadata(metaDataContent);
        }

        private FASAssert GetEntityValidateResult(IMetaDataContent metaDataContent, CRUDType crudType = CRUDType.Create)
        {
            FASAssert Assert = new FASAssert();
            StateMachineMetadata Meta = metaDataContent as StateMachineMetadata;
            Assert.IsNotNull(Meta, $"请检查IMetaDataContent参数");
            Assert.FailIfErrorResult(); //如果为空引用直接抛出异常
            if (!string.IsNullOrWhiteSpace(metaDataContent?.MetaData?.MetaTypeID))
                MetaDataType = metaDataContent?.MetaData?.MetaTypeID;
            var unifyCode = $"元数据类型{MetaDataType}的元数据Code:{Meta.MetaDataCode},ID:{Meta.MetaDataID}";

            /***********通用系统字段校验**********/
            StringBuilder errmsg = new StringBuilder();
            //MetaDataID,MetaDataCode,MetaDataName等字段校验
            var systemFieldsCheckResult = EntityCheckTools.CheckSystemFields(Meta);
            Assert.IsTrue(systemFieldsCheckResult.Result, systemFieldsCheckResult.ErrorMsg);

            if (crudType == CRUDType.Create)
            {
                var MetaDataInfo = metaDataContent.MetaData;
                Assert.IsNotNull(MetaDataInfo, $"{unifyCode}的系统字段:{nameof(metaDataContent.MetaData)}不能为空!");
                //租户ID验证
                Assert.IsNotNull(MetaDataInfo.TenantId, $"{unifyCode}的系统字段:{nameof(MetaDataInfo.TenantId)}不能为空!");

            }

            /*********************业务校验***********************/
            /*********************SM校验***********************/
            Assert.IsNotNull(Meta.CDOMetadataID, $"{unifyCode}所属的CDO {nameof(Meta.CDOMetadataID)}字段不能为空！", true);
            Assert.IsNotNull(Meta.CDOColKey, $"{unifyCode}所属的CDO状态字段 {nameof(Meta.CDOColKey)}字段不能为空！", true);
            /*********************CDO&ColKey***********************/
            var cdo = _compositeDataObjectLogic.GetCompositeDataObject(Meta.CDOMetadataID);
            Assert.IsNotNull(cdo, $"{unifyCode}所属的CDO:{Meta.CDOMetadataID}在数据库中找不到实例！", true);
            var ele = cdo.RootCompositeNodeObject.Elements.FirstOrDefault(e => (e.Alias ?? e.Name) == Meta.CDOColKey);   //使用列名匹配状态字段
            Assert.IsNotNull(ele, $"{unifyCode}所属的CDO:{Meta.CDOMetadataID}的状态字段:{Meta.CDOColKey}不存在！", true);
            var sdoid = ele.DataColumn.RelatedDataObjectID;
            var sdoPKType = ele.DataColumn.RelatedDataObjectPrimaryKey.ApplicationDataType;
            if (crudType == CRUDType.Create)
            {
                Assert.IsTrue(DataTypeUtil.ConvertToDataType(sdoPKType) == DataType.Int, $"{unifyCode}所属" +
                            $"CDO:{cdo.Code}主节点的元素ele:{ele.ID}" +
                            $"关联的column:{ele.DataColumnID}" +
                            $"关联的外键sdo:{sdoid}的主键列:{ele.DataColumn.RelatedDataObjectPrimaryKey.ID}" +
                            $"类型:{sdoPKType}错误，必须是Int类型");
                Assert.IsTrue(_stateMachineMetadataLogic.UniqueCheck(Meta), $"{unifyCode},一个CDO:{Meta.CDOMetadataID}的状态字段:{Meta.CDOColKey}只能绑定一个状态机,请检查！");
            }
            /*********************State&Rule校验***********************/
            Assert.IsTrue(Meta.States != null && Meta.States.Count > 0, $"{unifyCode}状态列表不能为空", true);

            /*********************Transition&Event&Action校验***********************/
            Assert.IsTrue(Meta.Transitions != null && Meta.Transitions.Count > 0, $"{unifyCode}状态变换列表不能为空", true);
            Assert.IsTrue(Meta.Events != null && Meta.Events.Count > 0, $"{unifyCode}事件列表不能为空", true);
            var eventid = Meta.Transitions?.FirstOrDefault(t => string.IsNullOrEmpty(t.FromStateID))?.EventID;
            Assert.IsNotNull(eventid, $"{unifyCode}获取初始事件EventID失败", true);
            var eventKey = Meta.Events?.FirstOrDefault(e => e.ID == eventid)?.Key;
            Assert.IsNotNull(eventKey, $"{unifyCode}获取初始事件EventKey失败", true);

            /**********获取时加入的额外控制***********/
            if (crudType == CRUDType.Retrive)
            {
               
            }

            return Assert;
        }
         
    }
}
